<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>JDK8 String源码 | Joey</title><meta name="keywords" content="Java,源码,String"><meta name="author" content="方陈勇"><meta name="copyright" content="方陈勇"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="[TOC] JDK8 String1.定义public final class String implements java.io.Serializable, Comparable&lt;String&gt;, CharSequence   从上可以看出：  String 是final类，不能被继承。 实现了java.io.Serializable接口，这个序列化接口没有任何方法和域，仅用于标识序">
<meta property="og:type" content="article">
<meta property="og:title" content="JDK8 String源码">
<meta property="og:url" content="https://fangchenyong.top/2019/09/06/Java-%E6%BA%90%E7%A0%81-JDK8-String/index.html">
<meta property="og:site_name" content="Joey">
<meta property="og:description" content="[TOC] JDK8 String1.定义public final class String implements java.io.Serializable, Comparable&lt;String&gt;, CharSequence   从上可以看出：  String 是final类，不能被继承。 实现了java.io.Serializable接口，这个序列化接口没有任何方法和域，仅用于标识序">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG">
<meta property="article:published_time" content="2019-09-05T16:00:00.000Z">
<meta property="article:modified_time" content="2020-06-09T08:17:39.118Z">
<meta property="article:author" content="方陈勇">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="源码">
<meta property="article:tag" content="String">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://fangchenyong.top/2019/09/06/Java-%E6%BA%90%E7%A0%81-JDK8-String/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2020-06-09 16:17:39'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    })(window)</script><meta name="generator" content="Hexo 5.4.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/3FD9B055-6361-49B7-B8CE-5BA9144BD27F.JPG" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">43</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">51</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">53</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> List</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Joey</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> List</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> Link</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">JDK8 String源码</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2019-09-05T16:00:00.000Z" title="发表于 2019-09-06 00:00:00">2019-09-06</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2020-06-09T08:17:39.118Z" title="更新于 2020-06-09 16:17:39">2020-06-09</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/">Java</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/%E6%BA%90%E7%A0%81/">源码</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java/%E6%BA%90%E7%A0%81/String/">String</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">9.7k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>42分钟</span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><p>[TOC]</p>
<h1 id="JDK8-String"><a href="#JDK8-String" class="headerlink" title="JDK8 String"></a>JDK8 String</h1><h2 id="1-定义"><a href="#1-定义" class="headerlink" title="1.定义"></a>1.定义</h2><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">String</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span>, <span class="title">Comparable</span>&lt;<span class="title">String</span>&gt;, <span class="title">CharSequence</span> </span></span><br></pre></td></tr></table></figure>

<p>从上可以看出：</p>
<ul>
<li>String 是final类，不能被继承。</li>
<li>实现了java.io.Serializable接口，这个序列化接口没有任何方法和域，仅用于标识序列化的语意。</li>
<li>实现了Comparable<String>接口，这个接口只有一个compareTo(T 0)接口，用于对两个实例化对象比较大小。</li>
<li>实现了CharSequence接口，这个接口是一个只读的字符序列。包括length(), charAt(int index), subSequence(int start, int end)这几个API接口，值得一提的是，StringBuffer和StringBuild也是实现了该接口。</li>
</ul>
<h2 id="2-主要字段属性"><a href="#2-主要字段属性" class="headerlink" title="2.主要字段属性"></a>2.主要字段属性</h2><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//用来存字符串，是一个final的char型数组，不可修改</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">char</span>[] value;</span><br><span class="line"><span class="comment">//缓存字符串的哈希。而hash是String实例化的hashcode的一个缓存。因为String经常被用于比较，比如在HashMap中。如果每次进行比较都重新计算hashcode的值的话，那无疑是比较麻烦的，而保存一个hashcode的缓存无疑能优化这样的操作。</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> hash;</span><br><span class="line"><span class="comment">//实现序列化的标识</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = -<span class="number">6849794470754667710L</span>;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> ObjectStreamField[] serialPersistentFields </span><br><span class="line">											= <span class="keyword">new</span> ObjectStreamField[<span class="number">0</span>];</span><br><span class="line"><span class="comment">//静态内部类，用于忽略大小写得比较两个字符串。</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Comparator&lt;String&gt; CASE_INSENSITIVE_ORDER</span><br><span class="line">											= <span class="keyword">new</span> CaseInsensitiveComparator(<span class="keyword">null</span>);</span><br></pre></td></tr></table></figure>

<h2 id="3-构造方法"><a href="#3-构造方法" class="headerlink" title="3.构造方法"></a>3.构造方法</h2><table>
<thead>
<tr>
<th>Constructor</th>
<th>Method</th>
</tr>
</thead>
<tbody><tr>
<td>String()</td>
<td>初始化新创建的 <code>String</code>对象，使其表示空字符序列。</td>
</tr>
<tr>
<td>String(byte[] bytes)</td>
<td>通过使用平台的默认字符集解码指定的字节数组来构造新的 <code>String</code> 。</td>
</tr>
<tr>
<td>String(byte[] bytes, Charset charset)</td>
<td>构造一个新的<code>String</code>由指定用指定的字节的数组解码charset 。</td>
</tr>
<tr>
<td>String(byte[] bytes, int offset, int length)</td>
<td>通过使用平台的默认字符集解码指定的字节子阵列来构造新的 <code>String</code> 。</td>
</tr>
<tr>
<td>String(byte[] bytes,  int offset, int length,Charset charset)</td>
<td>构造一个新的<code>String</code>通过使用指定的指定字节子阵列解码charset  。</td>
</tr>
<tr>
<td>String(byte[] bytes,  int offset, int length, String charsetName)</td>
<td>构造一个新的 <code>String</code>通过使用指定的字符集解码指定的字节子阵列。</td>
</tr>
<tr>
<td>String(byte[] bytes,  String charsetName)</td>
<td>构造一个新的<code>String</code>由指定用指定的字节的数组解码charset 。</td>
</tr>
<tr>
<td>String(char[] value)</td>
<td>分配一个新的 <code>String</code> ，以便它表示当前包含在字符数组参数中的字符序列。</td>
</tr>
<tr>
<td>String(char[] value,  int offset, int count)</td>
<td>分配一个新的 <code>String</code> ，其中包含字符数组参数的子阵列中的字符。</td>
</tr>
<tr>
<td>String(int[] codePoints,  int offset, int count)</td>
<td>分配一个新的 <code>String</code> ，其中包含 Unicode code  point数组参数的子阵列中的字符 。</td>
</tr>
<tr>
<td>String(String original)</td>
<td>初始化新创建的<code>String</code>对象，使其表示与参数相同的字符序列;  换句话说，新创建的字符串是参数字符串的副本。</td>
</tr>
<tr>
<td>String(StringBuffer buffer)</td>
<td>分配一个新的字符串，其中包含当前包含在字符串缓冲区参数中的字符序列。</td>
</tr>
<tr>
<td>String(StringBuilder builder)</td>
<td>分配一个新的字符串，其中包含当前包含在字符串构建器参数中的字符序列。</td>
</tr>
</tbody></table>
<h2 id="4-常用方法"><a href="#4-常用方法" class="headerlink" title="4.常用方法"></a>4.常用方法</h2><ul>
<li><p><strong>长度和判空</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//返回的就是char数组的长度，中文是两个字节的，char也是两个字节的。String a=&quot;中文&quot;，a的长度为2。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">length</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> value.length;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//当char数组的长度为0，则代表String为&quot;&quot;，是空字符串</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isEmpty</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> value.length == <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p><strong>charAt、codePointAt类函数</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//返回String对象的char数组index位置的元素</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">char</span> <span class="title">charAt</span><span class="params">(<span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> ((index &lt; <span class="number">0</span>) || (index &gt;= value.length)) &#123;   <span class="comment">//index不允许小于0，不允许大于等于String的长度</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(index);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> value[index];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回String对象的char数组index位置的元素的ASSIC码(int类型)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">codePointAt</span><span class="params">(<span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> ((index &lt; <span class="number">0</span>) || (index &gt;= value.length)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(index);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Character.codePointAtImpl(value, index, value.length);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回index位置元素的前一个元素的ASSIC码(int型)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">codePointBefore</span><span class="params">(<span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i = index - <span class="number">1</span>;  <span class="comment">//获得index前一个元素的索引位置</span></span><br><span class="line">    <span class="keyword">if</span> ((i &lt; <span class="number">0</span>) || (i &gt;= value.length)) &#123; <span class="comment">//所以，index不能等于0，因为i = 0 - 1 = -1</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(index);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Character.codePointBeforeImpl(value, index, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 方法返回的是代码点个数，是实际上的字符个数,功能类似于length()</span></span><br><span class="line"><span class="comment">* 对于正常的String来说，length方法和codePointCount没有区别，都是返回字符个数。</span></span><br><span class="line"><span class="comment">* 但当String是Unicode类型时则有区别了。</span></span><br><span class="line"><span class="comment">* 例如：String str = “/uD835/uDD6B” (即使 &#x27;Z&#x27; ), length() = 2 ,codePointCount() = 1 </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">codePointCount</span><span class="params">(<span class="keyword">int</span> beginIndex, <span class="keyword">int</span> endIndex)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (beginIndex &lt; <span class="number">0</span> || endIndex &gt; value.length || beginIndex &gt; endIndex) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IndexOutOfBoundsException();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 也是相对Unicode字符集而言的，从index索引位置算起，偏移codePointOffset个位置，返回偏移后的位置是多少</span></span><br><span class="line"><span class="comment">* 例如，index = 2 ，codePointOffset = 3 ，maybe返回 5 </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">offsetByCodePoints</span><span class="params">(<span class="keyword">int</span> index, <span class="keyword">int</span> codePointOffset)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (index &lt; <span class="number">0</span> || index &gt; value.length) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IndexOutOfBoundsException();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> Character.offsetByCodePointsImpl(value, <span class="number">0</span>, value.length,</span><br><span class="line">                                            index, codePointOffset);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p><strong>getChars、getBytes类函数</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个不对外的方法，是给String内部调用的，因为它是没有访问修饰符的，只允许同一包下的类访问</span></span><br><span class="line"><span class="comment">* 参数：dst[]是目标数组，dstBegin是目标数组的偏移量，既要复制过去的起始位置(从目标数组的什么位置覆盖)</span></span><br><span class="line"><span class="comment">* 作用就是将String的字符数组value整个复制到dst字符数组中，在dst数组的dstBegin位置开始拷贝</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">getChars</span><span class="params">(<span class="keyword">char</span> dst[], <span class="keyword">int</span> dstBegin)</span> </span>&#123;</span><br><span class="line">    System.arraycopy(value, <span class="number">0</span>, dst, dstBegin, value.length);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 得到char字符数组，原理是getChars() 方法将一个字符串的字符复制到目标字符数组中。 </span></span><br><span class="line"><span class="comment">* 参数：srcBegin是原始字符串的起始位置，srcEnd是原始字符串要复制的字符末尾的后一个位置(既复制区域不包括srcEnd)</span></span><br><span class="line"><span class="comment">* dst[]是目标字符数组，dstBegin是目标字符的复制偏移量，复制的字符从目标字符数组的dstBegin位置开始覆盖。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">getChars</span><span class="params">(<span class="keyword">int</span> srcBegin, <span class="keyword">int</span> srcEnd, <span class="keyword">char</span> dst[], <span class="keyword">int</span> dstBegin)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (srcBegin &lt; <span class="number">0</span>) &#123;           <span class="comment">//如果srcBegin小于，抛异常</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(srcBegin);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (srcEnd &gt; value.length) &#123;  <span class="comment">//如果srcEnd大于字符串的长度，抛异常</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(srcEnd);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (srcBegin &gt; srcEnd) &#123;      <span class="comment">//如果原始字符串其实位置大于末尾位置，抛异常</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(srcEnd - srcBegin);</span><br><span class="line">    &#125;</span><br><span class="line">    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//获得charsetName编码格式的bytes数组</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">byte</span>[] getBytes(String charsetName)</span><br><span class="line">    <span class="keyword">throws</span> UnsupportedEncodingException &#123;</span><br><span class="line">    <span class="keyword">if</span> (charsetName == <span class="keyword">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    <span class="keyword">return</span> StringCoding.encode(charsetName, value, <span class="number">0</span>, value.length);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//与上个方法类似，java内部存储字符串使用的unicode编码，注意编码转换！！！</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">byte</span>[] getBytes(Charset charset) &#123;</span><br><span class="line">    <span class="keyword">if</span> (charset == <span class="keyword">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    <span class="keyword">return</span> StringCoding.encode(charset, value, <span class="number">0</span>, value.length);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用平台默认的编码格式获得bytes数组</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">byte</span>[] getBytes() &#123;</span><br><span class="line">    <span class="keyword">return</span> StringCoding.encode(value, <span class="number">0</span>, value.length);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>  <strong>注意：</strong></p>
<ul>
<li>getChars是没有返回值的 ，使用System.arraycopy()方法直接拷贝至目标数组中，并且目标数组有个@NotNull非空注解，否则会抛出java.lang.ArrayIndexOutOfBoundsException异常。</li>
<li>getBytes是由返回值的。</li>
</ul>
</li>
<li><p><strong>equals类函数</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* String的equals方法，重写了Object的equals方法（区分大小写）</span></span><br><span class="line"><span class="comment">* 比较的是两个字符串的值是否相等</span></span><br><span class="line"><span class="comment">* 参数是一个Object对象，而不是一个String对象。这是因为重写的是Object的equals方法，所以是Object</span></span><br><span class="line"><span class="comment">* 如果是String自己独有的方法，则可以传入String对象，不用多此一举</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">* 实例：str1.equals(str2)</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object anObject)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">this</span> == anObject) &#123;   <span class="comment">//首先判断形参str2是否跟当前对象str1是同一个对象，既比较地址是否相等</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;          <span class="comment">//如果地址相等，那么自然值也相等，毕竟是同一个字符串对象</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (anObject <span class="keyword">instanceof</span> String) &#123;  <span class="comment">//判断str2对象是否是一个String类型，过滤掉非String类型的比较</span></span><br><span class="line">        String anotherString = (String)anObject; <span class="comment">//如果是String类型，转换为String类型</span></span><br><span class="line">        <span class="keyword">int</span> n = value.length;                    <span class="comment">//获得当前对象str1的长度</span></span><br><span class="line">        <span class="keyword">if</span> (n == anotherString.value.length) &#123;   <span class="comment">//比较str1的长度和str2的长度是否相等</span></span><br><span class="line">            <span class="keyword">char</span> v1[] = value;  <span class="comment">//v1为当前对象str1的值，v2为参数对象str2的值</span></span><br><span class="line">            <span class="keyword">char</span> v2[] = anotherString.value;</span><br><span class="line">            <span class="keyword">int</span> i = <span class="number">0</span>;                <span class="comment">//就类似于for的int i =0的作用，因为这里使用while</span></span><br><span class="line">            <span class="keyword">while</span> (n-- != <span class="number">0</span>) &#123;                <span class="comment">//每次循环长度-1,直到长度消耗完，循环结束 </span></span><br><span class="line">                <span class="keyword">if</span> (v1[i] != v2[i])              <span class="comment">//同索引位置的字符元素逐一比较</span></span><br><span class="line">                    <span class="keyword">return</span> <span class="keyword">false</span>;                <span class="comment">//只要有一个不相等，则返回false</span></span><br><span class="line">                i++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;                     <span class="comment">//如比较期间没有问题，则说明相等，返回true</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这也是一个String的equals方法，与上一个方法不同，该方法(不区分大小写)，从名字也能看出来</span></span><br><span class="line"><span class="comment">* 是对String的equals方法的补充。</span></span><br><span class="line"><span class="comment">* 这里参数这是一个String对象，而不是Object了，因为这是String本身的方法，不是重写谁的方法</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equalsIgnoreCase</span><span class="params">(String anotherString)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (<span class="keyword">this</span> == anotherString) ? <span class="keyword">true</span>        <span class="comment">//一样，先判断是否为同一个对象</span></span><br><span class="line">        : (anotherString != <span class="keyword">null</span>) </span><br><span class="line">    		&amp;&amp; (anotherString.value.length == value.length) <span class="comment">//再判断长度是否相等</span></span><br><span class="line">    		&amp;&amp; regionMatches(<span class="keyword">true</span>, <span class="number">0</span>, anotherString, <span class="number">0</span>, value.length);  <span class="comment">//再执行regionMatchs方法 </span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个公有的比较方法，参数是StringBuffer类型</span></span><br><span class="line"><span class="comment">* 实际调用的是contentEquals(CharSequence cs)方法，可以说是StringBuffer的特供版</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">contentEquals</span><span class="params">(StringBuffer sb)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> contentEquals((CharSequence)sb);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个私有方法，特供给比较StringBuffer和StringBuilder使用的。</span></span><br><span class="line"><span class="comment">* 比如在contentEquals方法中使用，参数是AbstractStringBuilder抽象类的子类</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">boolean</span> <span class="title">nonSyncContentEquals</span><span class="params">(AbstractStringBuilder sb)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> v1[] = value;               <span class="comment">//当前String对象的值</span></span><br><span class="line">    <span class="keyword">char</span> v2[] = sb.getValue();       <span class="comment">//AbstractStringBuilder子类对象的值</span></span><br><span class="line">    <span class="keyword">int</span> n = v1.length;         <span class="comment">//后面就不说了，其实跟equals方法是一样的，只是少了一些判断</span></span><br><span class="line">    <span class="keyword">if</span> (n != sb.length()) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v1[i] != v2[i]) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个常用于String对象跟StringBuffer和StringBuilder比较的方法</span></span><br><span class="line"><span class="comment">* 参数是StringBuffer或StringBuilder或String或CharSequence</span></span><br><span class="line"><span class="comment">* StringBuffer和StringBuilder和String都实现了CharSequence接口</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">contentEquals</span><span class="params">(CharSequence cs)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// Argument is a StringBuffer, StringBuilder</span></span><br><span class="line">    <span class="keyword">if</span> (cs <span class="keyword">instanceof</span> AbstractStringBuilder) &#123;   <span class="comment">//如果是AbstractStringBuilder抽象类或其子类</span></span><br><span class="line">        <span class="keyword">if</span> (cs <span class="keyword">instanceof</span> StringBuffer) &#123;        <span class="comment">//如果是StringBuffer类型，进入同步块</span></span><br><span class="line">            <span class="keyword">synchronized</span>(cs) &#123;</span><br><span class="line">                <span class="keyword">return</span> nonSyncContentEquals((AbstractStringBuilder)cs);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;                            <span class="comment">//如果是StringBuilder类型，则进入非同步块</span></span><br><span class="line">            <span class="keyword">return</span> nonSyncContentEquals((AbstractStringBuilder)cs);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/***下面就是String和CharSequence类型的比较算法*****/</span></span><br><span class="line">    <span class="comment">// Argument is a String</span></span><br><span class="line">    <span class="keyword">if</span> (cs <span class="keyword">instanceof</span> String) &#123;                    </span><br><span class="line">        <span class="keyword">return</span> equals(cs);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// Argument is a generic CharSequence</span></span><br><span class="line">    <span class="keyword">char</span> v1[] = value;</span><br><span class="line">    <span class="keyword">int</span> n = v1.length;</span><br><span class="line">    <span class="keyword">if</span> (n != cs.length()) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v1[i] != cs.charAt(i)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>  <strong>注意：</strong></p>
<ul>
<li>equals()方法怎么重写Object中的equals()实现对String内容的判断</li>
<li>equalsIgnoreCase()方法是对equals()方法补充，不区分大小写的判断，是String类自己的方法</li>
<li>contentEquals()则是用于String对象与4种类型的判断，通常用于跟StringBuilder和StringBuffer的判断,也是对equals方法的一个补充，如果是参数是String类型，就调用equals()方法</li>
</ul>
</li>
<li><p><strong>regionMatchs()方法</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个类似于equals的方法，比较的是字符串的片段，也即是部分区域的比较</span></span><br><span class="line"><span class="comment">* toffset是当前字符串的比较起始位置(偏移量),other是要比较的String对象参数，ooffset是要参数String的比较片段起始位置，len是两个字符串要比较的片段的长度大小</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">* 例子：String str1 = &quot;0123456&quot;,Str2 = &quot;0123456789&quot;; </span></span><br><span class="line"><span class="comment">* str1.regionMatchs(0,str2,0,6);意思是str1从0位置开始于str2的0位置开始比较6个长度的字符串片段</span></span><br><span class="line"><span class="comment">* 相等则返回 true,不等返回false </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">regionMatches</span><span class="params">(<span class="keyword">int</span> toffset, String other, <span class="keyword">int</span> ooffset, <span class="keyword">int</span> len)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> ta[] = value;  <span class="comment">//当前对象的值</span></span><br><span class="line">    <span class="keyword">int</span> to = toffset;   <span class="comment">//当前对象的比较片段的起始位置，既偏移量</span></span><br><span class="line">    <span class="keyword">char</span> pa[] = other.value;  <span class="comment">//参数，既比较字符串的值</span></span><br><span class="line">    <span class="keyword">int</span> po = ooffset;         <span class="comment">//比较字符串的起始位置</span></span><br><span class="line">    <span class="comment">// Note: toffset, ooffset, or len might be near -1&gt;&gt;&gt;1.</span></span><br><span class="line">    <span class="keyword">if</span> ((ooffset &lt; <span class="number">0</span>) || (toffset &lt; <span class="number">0</span>)  <span class="comment">//起始位置不小于0或起始位置不大于字符串长度 - 片段长度，大于就截取不到这么长的片段了</span></span><br><span class="line">        || (toffset &gt; (<span class="keyword">long</span>)value.length - len)</span><br><span class="line">        || (ooffset &gt; (<span class="keyword">long</span>)other.value.length - len)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;      <span class="comment">//惊讶脸，居然不是抛异常，而是返回false</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (len-- &gt; <span class="number">0</span>) &#123;               <span class="comment">//使用while循环，当然也可以使for循环</span></span><br><span class="line">        <span class="keyword">if</span> (ta[to++] != pa[po++]) &#123;   <span class="comment">//片段区域的字符元素逐个比较</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这个跟上面的方法一样，只不过多了一个参数，既ignoreCase,既是否为区分大小写。</span></span><br><span class="line"><span class="comment">* 是equalsIgnoreCase()方法的片段比较版本，实际上equalsIgnoreCase()也是调用regionMatches函数</span></span><br><span class="line"><span class="comment">*/</span>	</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">regionMatches</span><span class="params">(<span class="keyword">boolean</span> ignoreCase, <span class="keyword">int</span> toffset,</span></span></span><br><span class="line"><span class="function"><span class="params">                             String other, <span class="keyword">int</span> ooffset, <span class="keyword">int</span> len)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> ta[] = value;</span><br><span class="line">    <span class="keyword">int</span> to = toffset;</span><br><span class="line">    <span class="keyword">char</span> pa[] = other.value;</span><br><span class="line">    <span class="keyword">int</span> po = ooffset;</span><br><span class="line">    <span class="comment">// Note: toffset, ooffset, or len might be near -1&gt;&gt;&gt;1.</span></span><br><span class="line">    <span class="keyword">if</span> ((ooffset &lt; <span class="number">0</span>) || (toffset &lt; <span class="number">0</span>)</span><br><span class="line">        || (toffset &gt; (<span class="keyword">long</span>)value.length - len)</span><br><span class="line">        || (ooffset &gt; (<span class="keyword">long</span>)other.value.length - len)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//上面的解释同上</span></span><br><span class="line">    <span class="keyword">while</span> (len-- &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">char</span> c1 = ta[to++];</span><br><span class="line">        <span class="keyword">char</span> c2 = pa[po++];</span><br><span class="line">        <span class="keyword">if</span> (c1 == c2) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (ignoreCase) &#123;   <span class="comment">//当ignoreCase为true时，既忽视大小写时</span></span><br><span class="line">            <span class="comment">// If characters don&#x27;t match but case may be ignored,</span></span><br><span class="line">            <span class="comment">// try converting both characters to uppercase.</span></span><br><span class="line">            <span class="comment">// If the results match, then the comparison scan should</span></span><br><span class="line">            <span class="comment">// continue.</span></span><br><span class="line">            <span class="keyword">char</span> u1 = Character.toUpperCase(c1);   <span class="comment">//片段中每个字符转换为大写</span></span><br><span class="line">            <span class="keyword">char</span> u2 = Character.toUpperCase(c2);</span><br><span class="line">            <span class="keyword">if</span> (u1 == u2) &#123; <span class="comment">//大写比较一次，如果相等则不执行下面的语句，进入下一个循环</span></span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// Unfortunately, conversion to uppercase does not work properly</span></span><br><span class="line">            <span class="comment">// for the Georgian alphabet, which has strange rules about case</span></span><br><span class="line">            <span class="comment">// conversion.  So we need to make one last check before</span></span><br><span class="line">            <span class="comment">// exiting.</span></span><br><span class="line">            <span class="keyword">if</span> (Character.toLowerCase(u1) == Character.toLowerCase(u2)) &#123;</span><br><span class="line">                <span class="comment">//每个字符换行成小写比较一次</span></span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>  <strong>从上可以看出：</strong></p>
<ul>
<li>片段比较时针对的是String对象。所以如果要跟StringBuffer和StringBuilder比较，那么要toString。</li>
<li>两个字符串之间的片段比较，使用regionMatches，完整的比较，使用equals。</li>
</ul>
</li>
<li><p><strong>compareTo类函数和CaseInsensitiveComparator静态内部类</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个比较字符串中字符大小的函数，因为String实现了Comparable&lt;String&gt;接口，所以重写了compareTo方法</span></span><br><span class="line"><span class="comment">* Comparable是排序接口。若一个类实现了Comparable接口，就意味着该类支持排序。</span></span><br><span class="line"><span class="comment">* 实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">* 参数是需要比较的另一个String对象</span></span><br><span class="line"><span class="comment">* 返回的int类型，正数为大，负数为小，是基于字符的ASSIC码比较的</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(String anotherString)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> len1 = value.length;                  <span class="comment">//当前对象的长度</span></span><br><span class="line">    <span class="keyword">int</span> len2 = anotherString.value.length;    <span class="comment">//比较对象的长度</span></span><br><span class="line">    <span class="keyword">int</span> lim = Math.min(len1, len2);           <span class="comment">//获得最小长度</span></span><br><span class="line">    <span class="keyword">char</span> v1[] = value;                        <span class="comment">//获得当前对象的值</span></span><br><span class="line">    <span class="keyword">char</span> v2[] = anotherString.value;          <span class="comment">//获得比较对象的值</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> k = <span class="number">0</span>;                    <span class="comment">//相当于for的int k = 0,就是为while循环的数组服务的</span></span><br><span class="line">    <span class="keyword">while</span> (k &lt; lim) &#123;             <span class="comment">//当当前索引小于两个字符串中较短字符串的长度时，循环继续</span></span><br><span class="line">        <span class="keyword">char</span> c1 = v1[k];          <span class="comment">//获得当前对象的字符</span></span><br><span class="line">        <span class="keyword">char</span> c2 = v2[k];          <span class="comment">//获得比较对象的字符</span></span><br><span class="line">        <span class="keyword">if</span> (c1 != c2) &#123;    <span class="comment">//从前向后遍历，只要其实一个不相等，返回字符ASSIC的差值,int类型</span></span><br><span class="line">            <span class="keyword">return</span> c1 - c2;</span><br><span class="line">        &#125;</span><br><span class="line">        k++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> len1 - len2;   <span class="comment">//如果两个字符串同样位置的索引都相等，返回长度差值，完全相等则为0</span></span><br><span class="line">&#125;</span><br><span class="line">	</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">*  这时一个类似compareTo功能的方法，但是不是comparable接口的方法，是String本身的方法</span></span><br><span class="line"><span class="comment">*  使用途径，我目前只知道可以用来不区分大小写的比较大小，但是不知道如何让它被工具类Collections和Arrays运用</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareToIgnoreCase</span><span class="params">(String str)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> CASE_INSENSITIVE_ORDER.compare(<span class="keyword">this</span>, str);</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个饿汉单例模式，是String类型的一个不区分大小写的比较器</span></span><br><span class="line"><span class="comment">* 提供给Collections和Arrays的sort方法使用</span></span><br><span class="line"><span class="comment">* 例如：Arrays.sort(strs,String.CASE_INSENSITIVE_ORDER);</span></span><br><span class="line"><span class="comment">* 效果就是会将strs字符串数组中的字符串对象进行忽视大小写的排序</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Comparator&lt;String&gt; CASE_INSENSITIVE_ORDER</span><br><span class="line">                                         = <span class="keyword">new</span> CaseInsensitiveComparator();</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这一个私有的静态内部类，只允许String类本身调用</span></span><br><span class="line"><span class="comment">* 实现了序列化接口和比较器接口，comparable接口和comparator是有区别的</span></span><br><span class="line"><span class="comment">* 重写了compare方法，该静态内部类实际就是一个String类的比较器</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">CaseInsensitiveComparator</span></span></span><br><span class="line"><span class="class">    <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">String</span>&gt;, <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span> </span>&#123;</span><br><span class="line">    <span class="comment">// use serialVersionUID from JDK 1.2.2 for interoperability</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">8575799808933029326L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(String s1, String s2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> n1 = s1.length();                 <span class="comment">//s1字符串的长度</span></span><br><span class="line">        <span class="keyword">int</span> n2 = s2.length();                 <span class="comment">//s2字符串的长度</span></span><br><span class="line">        <span class="keyword">int</span> min = Math.min(n1, n2);           <span class="comment">//获得最小长度 </span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; min; i++) &#123;</span><br><span class="line">            <span class="keyword">char</span> c1 = s1.charAt(i);           <span class="comment">//逐一获得字符串i位置的字符</span></span><br><span class="line">            <span class="keyword">char</span> c2 = s2.charAt(i);</span><br><span class="line">            <span class="keyword">if</span> (c1 != c2) &#123;                   <span class="comment">//部分大小写比较一次</span></span><br><span class="line">                c1 = Character.toUpperCase(c1);    <span class="comment">//转换大写比较一次</span></span><br><span class="line">                c2 = Character.toUpperCase(c2);</span><br><span class="line">                <span class="keyword">if</span> (c1 != c2) &#123;</span><br><span class="line">                    c1 = Character.toLowerCase(c1);  <span class="comment">//转换小写比较一次</span></span><br><span class="line">                    c2 = Character.toLowerCase(c2);</span><br><span class="line">                    <span class="keyword">if</span> (c1 != c2) &#123;                  <span class="comment">//返回字符差值</span></span><br><span class="line">                        <span class="comment">// No overflow because of numeric promotion</span></span><br><span class="line">                        <span class="keyword">return</span> c1 - c2;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n1 - n2;<span class="comment">//如果字符相等，但长度不等，则返回长度差值，短的教小，所以小-大为负数</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** Replaces the de-serialized object. */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> Object <span class="title">readResolve</span><span class="params">()</span> </span>&#123; <span class="keyword">return</span> CASE_INSENSITIVE_ORDER; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>  以上的代码可以看出：</p>
<p>  以上的最大问题可以能就是为什么要有个静态内部类，为什么实现了compareTo又有compare，移步到下面，有解答</p>
<p>  String实现了comparable接口，重写了compareTo方法，可以用于自己写类进行判断排序，也可以使用collections，Arrays工具类的sort进行排序。只有集合或数组中的元素实现了comparable接口，并重写了compareTo才能使用工具类排序。</p>
<p>  CASE_INSENSITIVE_ORDER是一个单例，是String提供为外部的比较器，该比较器的作用是忽视大小写进行比较，我们可以通过Collections或Arrays的sort方法将CASE_INSENSITIVE_ORDER比较器作为参数传入，进行排序。</p>
</li>
<li><p><strong>startWith、endWith类函数</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 作用就是当前对象[toffset,toffset + prefix.value.lenght]区间的字符串片段等于prefix</span></span><br><span class="line"><span class="comment">* 也可以说当前对象的toffset位置开始是否以prefix作为前缀</span></span><br><span class="line"><span class="comment">* prefix是需要判断的前缀字符串，toffset是当前对象的判断起始位置</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">startsWith</span><span class="params">(String prefix, <span class="keyword">int</span> toffset)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> ta[] = value;     <span class="comment">//获得当前对象的值</span></span><br><span class="line">    <span class="keyword">int</span> to = toffset;      <span class="comment">//获得需要判断的起始位置，偏移量</span></span><br><span class="line">    <span class="keyword">char</span> pa[] = prefix.value; <span class="comment">//获得前缀字符串的值</span></span><br><span class="line">    <span class="keyword">int</span> po = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">int</span> pc = prefix.value.length;</span><br><span class="line">    <span class="comment">// Note: toffset might be near -1&gt;&gt;&gt;1.</span></span><br><span class="line">    <span class="keyword">if</span> ((toffset &lt; <span class="number">0</span>) || (toffset &gt; value.length - pc)) &#123;  <span class="comment">//偏移量不能小于0且能截取pc个长度</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;  <span class="comment">//不能则返回false</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (--pc &gt;= <span class="number">0</span>) &#123;                  <span class="comment">//循环pc次，既prefix的长度</span></span><br><span class="line">        <span class="keyword">if</span> (ta[to++] != pa[po++]) &#123;      <span class="comment">//每次比较当前对象的字符串的字符是否跟prefix一样</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;                <span class="comment">//一样则pc--,to++,po++,有一个不同则返回false</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;  <span class="comment">//没有不一样则返回true，当前对象是以prefix在toffset位置做为开头</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 判断当前字符串对象是否以字符串prefix起头</span></span><br><span class="line"><span class="comment">* 是返回true,否返回fasle</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">startsWith</span><span class="params">(String prefix)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> startsWith(prefix, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 判断当前字符串对象是否以字符串prefix结尾</span></span><br><span class="line"><span class="comment">* 是返回true,否返回fasle</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">endsWith</span><span class="params">(String suffix)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//suffix是需要判断是否为尾部的字符串。</span></span><br><span class="line">    <span class="comment">//value.length - suffix.value.length是suffix在当前对象的起始位置</span></span><br><span class="line">    <span class="keyword">return</span> startsWith(suffix, value.length - suffix.value.length); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>  <strong>所以我们知道：</strong></p>
<ul>
<li>endsWith的实现也是startWith()，作用就是判断前后缀</li>
</ul>
</li>
<li><p><strong>hashCode()函数</strong></p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">   * 这是String字符串重写了Object类的hashCode方法。</span></span><br><span class="line"><span class="comment">   * 给由哈希表来实现的数据结构来使用，比如String对象要放入HashMap中。</span></span><br><span class="line"><span class="comment">   * 如果没有重写HashCode，或HaseCode质量很差则会导致严重的后果，既不靠谱的后果</span></span><br><span class="line"><span class="comment">   *</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">hashCode</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> h = hash;  <span class="comment">//hash是属性字段，是成员变量，所以默认为0</span></span><br><span class="line">    <span class="keyword">if</span> (h == <span class="number">0</span> &amp;&amp; value.length &gt; <span class="number">0</span>) &#123; <span class="comment">//如果hash为0，且字符串对象长度大于0，不为&quot;&quot;</span></span><br><span class="line">        <span class="keyword">char</span> val[] = value;   <span class="comment">//获得当前对象的值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//重点，String的哈希函数</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; value.length; i++) &#123;  <span class="comment">//遍历len次</span></span><br><span class="line">            h = <span class="number">31</span> * h + val[i]; <span class="comment">//每次都是31 * 每次循环获得的h +第i个字符的ASSIC码</span></span><br><span class="line">        &#125;</span><br><span class="line">        hash = h;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> h;  <span class="comment">//由此可见&quot;&quot;空字符对象的哈希值为0</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>  <strong>所以我们可以知道：</strong></p>
<ul>
<li>hashCode的重点就是哈希函数</li>
<li>String的哈希函数就是循环len次，每次循环体为 <code>31 * 每次循环获得的hash + 第i次循环的字符</code></li>
</ul>
</li>
<li><p>indexOf、lastIndexOf类函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 返回cn对应的字符在字符串中第一次出现的位置，从字符串的索引0位置开始遍历</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(<span class="keyword">int</span> ch)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> indexOf(ch, <span class="number">0</span>);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * index方法就是返回ch字符第一次在字符串中出现的位置</span></span><br><span class="line"><span class="comment"> * 既从fromIndex位置开始查找，从头向尾遍历，ch整数对应的字符在字符串中第一次出现的位置</span></span><br><span class="line"><span class="comment"> * -1代表字符串没有这个字符，整数代表字符第一次出现在字符串的位置</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(<span class="keyword">int</span> ch, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">final</span> <span class="keyword">int</span> max = value.length; <span class="comment">//获得字符串对象的长度</span></span><br><span class="line">       <span class="keyword">if</span> (fromIndex &lt; <span class="number">0</span>) &#123;             <span class="comment">//如果偏移量小于0，则代表偏移量为0，校正偏移量</span></span><br><span class="line">           fromIndex = <span class="number">0</span>;</span><br><span class="line">       &#125; <span class="keyword">else</span> <span class="keyword">if</span> (fromIndex &gt;= max) &#123;   <span class="comment">//如果偏移量大于最大长度，则返回-1，代表没有字符串没有ch对应的字符</span></span><br><span class="line">           <span class="comment">// Note: fromIndex might be near -1&gt;&gt;&gt;1.</span></span><br><span class="line">           <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">       &#125;</span><br><span class="line">    </span><br><span class="line">       <span class="keyword">if</span> (ch &lt; Character.MIN_SUPPLEMENTARY_CODE_POINT) &#123; <span class="comment">//emmm,这个判断，不懂</span></span><br><span class="line">           <span class="comment">// handle most cases here (ch is a BMP code point or a</span></span><br><span class="line">           <span class="comment">// negative value (invalid code point))</span></span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span>[] value = <span class="keyword">this</span>.value;             <span class="comment">//获得字符串值</span></span><br><span class="line">           <span class="keyword">for</span> (<span class="keyword">int</span> i = fromIndex; i &lt; max; i++) &#123;      <span class="comment">//从fromIndex位置开始向后遍历</span></span><br><span class="line">               <span class="keyword">if</span> (value[i] == ch) &#123;                    <span class="comment">//只有字符串中的某个位置的元素等于ch</span></span><br><span class="line">                   <span class="keyword">return</span> i;                            <span class="comment">//返回对应的位置，函数结束，既第一次出现的位置</span></span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">return</span> -<span class="number">1</span>;  <span class="comment">//如果没有出现，则返回-1</span></span><br><span class="line">       &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">           <span class="keyword">return</span> indexOfSupplementary(ch, fromIndex);  <span class="comment">//emmm,紧紧接着没看懂的地方</span></span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">int</span> <span class="title">indexOfSupplementary</span><span class="params">(<span class="keyword">int</span> ch, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (Character.isValidCodePoint(ch)) &#123;</span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span>[] value = <span class="keyword">this</span>.value;</span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span> hi = Character.highSurrogate(ch);</span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span> lo = Character.lowSurrogate(ch);</span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">int</span> max = value.length - <span class="number">1</span>;</span><br><span class="line">           <span class="keyword">for</span> (<span class="keyword">int</span> i = fromIndex; i &lt; max; i++) &#123;</span><br><span class="line">               <span class="keyword">if</span> (value[i] == hi &amp;&amp; value[i + <span class="number">1</span>] == lo) &#123;</span><br><span class="line">                   <span class="keyword">return</span> i;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 从尾部向头部遍历，返回cn第一次出现的位置，value.length - 1就是起点 </span></span><br><span class="line"><span class="comment">* 为了理解，我们可以认为是返回cn对应的字符在字符串中最后出现的位置</span></span><br><span class="line"><span class="comment">*  </span></span><br><span class="line"><span class="comment">* ch是字符对应的整数</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(<span class="keyword">int</span> ch)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> lastIndexOf(ch, value.length - <span class="number">1</span>);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 从尾部向头部遍历，从fromIndex开始作为起点，返回ch对应字符第一次在字符串出现的位置</span></span><br><span class="line"><span class="comment">* 既从头向尾遍历，返回cn对应字符在字符串中最后出现的一次位置，fromIndex为结束点</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(<span class="keyword">int</span> ch, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (ch &lt; Character.MIN_SUPPLEMENTARY_CODE_POINT) &#123;  <span class="comment">//之后不解释了,emmmmmmm</span></span><br><span class="line">           <span class="comment">// handle most cases here (ch is a BMP code point or a</span></span><br><span class="line">           <span class="comment">// negative value (invalid code point))</span></span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span>[] value = <span class="keyword">this</span>.value;</span><br><span class="line">           <span class="comment">//取最小值，作用就是校正，如果fromIndex传大了，就当时len - 1</span></span><br><span class="line">           <span class="keyword">int</span> i = Math.min(fromIndex, value.length - <span class="number">1</span>);   </span><br><span class="line">           <span class="keyword">for</span> (; i &gt;= <span class="number">0</span>; i--) &#123;      <span class="comment">//算法中是从后向前遍历，直到i&lt;0,退出循环</span></span><br><span class="line">               <span class="keyword">if</span> (value[i] == ch) &#123;  <span class="comment">//只有有相等，返回对应的索引位置</span></span><br><span class="line">                   <span class="keyword">return</span> i;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">return</span> -<span class="number">1</span>;   <span class="comment">//没有找到则返回-1</span></span><br><span class="line">       &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">           <span class="keyword">return</span> lastIndexOfSupplementary(ch, fromIndex);</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">private</span> <span class="keyword">int</span> <span class="title">lastIndexOfSupplementary</span><span class="params">(<span class="keyword">int</span> ch, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (Character.isValidCodePoint(ch)) &#123;</span><br><span class="line">           <span class="keyword">final</span> <span class="keyword">char</span>[] value = <span class="keyword">this</span>.value;</span><br><span class="line">           <span class="keyword">char</span> hi = Character.highSurrogate(ch);</span><br><span class="line">           <span class="keyword">char</span> lo = Character.lowSurrogate(ch);</span><br><span class="line">           <span class="keyword">int</span> i = Math.min(fromIndex, value.length - <span class="number">2</span>);</span><br><span class="line">           <span class="keyword">for</span> (; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line">               <span class="keyword">if</span> (value[i] == hi &amp;&amp; value[i + <span class="number">1</span>] == lo) &#123;</span><br><span class="line">                   <span class="keyword">return</span> i;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 返回第一次出现的字符串的位置</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(String str)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> indexOf(str, <span class="number">0</span>);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">* 从fromIndex开始遍历，返回第一次出现str字符串的位置</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(String str, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> indexOf(value, <span class="number">0</span>, value.length,</span><br><span class="line">               str.value, <span class="number">0</span>, str.value.length, fromIndex);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 这是一个不对外公开的静态函数</span></span><br><span class="line"><span class="comment">* source就是原始字符串，sourceOffset就是原始字符串的偏移量，起始位置。</span></span><br><span class="line"><span class="comment">* sourceCount就是原始字符串的长度，target就是要查找的字符串。</span></span><br><span class="line"><span class="comment">* fromIndex就是从原始字符串的第fromIndex开始遍历</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(<span class="keyword">char</span>[] source, <span class="keyword">int</span> sourceOffset, <span class="keyword">int</span> sourceCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           String target, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> indexOf(source, sourceOffset, sourceCount,</span><br><span class="line">                      target.value, <span class="number">0</span>, target.value.length,</span><br><span class="line">                      fromIndex);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 同是一个不对外公开的静态函数</span></span><br><span class="line"><span class="comment">* 比上更为强大。</span></span><br><span class="line"><span class="comment">* 多了一个targetOffset和targetCount，既代表别查找的字符串也可以被切割</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">indexOf</span><span class="params">(<span class="keyword">char</span>[] source, <span class="keyword">int</span> sourceOffset, <span class="keyword">int</span> sourceCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           <span class="keyword">char</span>[] target, <span class="keyword">int</span> targetOffset, <span class="keyword">int</span> targetCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (fromIndex &gt;= sourceCount) &#123;   <span class="comment">//如果查找的起点大于当前对象的大小</span></span><br><span class="line">        <span class="comment">//如果目标字符串的长度为0，则代表目标字符串为&quot;&quot;，&quot;&quot;在任何字符串都会出现</span></span><br><span class="line">        <span class="comment">//配合fromIndex &gt;= sourceCount,所以校正第一次出现在最尾部，仅仅是校正作用</span></span><br><span class="line">           <span class="keyword">return</span> (targetCount == <span class="number">0</span> ? sourceCount : -<span class="number">1</span>); </span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">if</span> (fromIndex &lt; <span class="number">0</span>) &#123;  <span class="comment">//也是校正，如果起始点小于0，则返回0</span></span><br><span class="line">           fromIndex = <span class="number">0</span>;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//如果目标字符串长度为0，代表为&quot;&quot;，则第一次出现在遍历起始点fromIndex</span></span><br><span class="line">       <span class="keyword">if</span> (targetCount == <span class="number">0</span>) &#123; </span><br><span class="line">           <span class="keyword">return</span> fromIndex;</span><br><span class="line">       &#125;</span><br><span class="line">    </span><br><span class="line">       <span class="keyword">char</span> first = target[targetOffset];   <span class="comment">//目标字符串的第一个字符</span></span><br><span class="line">       <span class="keyword">int</span> max = sourceOffset + (sourceCount - targetCount); <span class="comment">//最大遍历次数</span></span><br><span class="line">    </span><br><span class="line">       <span class="keyword">for</span> (<span class="keyword">int</span> i = sourceOffset + fromIndex; i &lt;= max; i++) &#123;</span><br><span class="line">           <span class="comment">/* Look for first character. */</span></span><br><span class="line">           <span class="keyword">if</span> (source[i] != first) &#123;</span><br><span class="line">               <span class="keyword">while</span> (++i &lt;= max &amp;&amp; source[i] != first);</span><br><span class="line">           &#125;</span><br><span class="line">    </span><br><span class="line">           <span class="comment">/* Found first character, now look at the rest of v2 */</span></span><br><span class="line">           <span class="keyword">if</span> (i &lt;= max) &#123;</span><br><span class="line">               <span class="keyword">int</span> j = i + <span class="number">1</span>;</span><br><span class="line">               <span class="keyword">int</span> end = j + targetCount - <span class="number">1</span>;</span><br><span class="line">               <span class="keyword">for</span> (<span class="keyword">int</span> k = targetOffset + <span class="number">1</span>; j &lt; end &amp;&amp; source[j]</span><br><span class="line">                       == target[k]; j++, k++);</span><br><span class="line">    </span><br><span class="line">               <span class="keyword">if</span> (j == end) &#123;</span><br><span class="line">                   <span class="comment">/* Found whole string. */</span></span><br><span class="line">                   <span class="keyword">return</span> i - sourceOffset;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 查找字符串Str最后一次出现的位置</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(String str)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> lastIndexOf(str, value.length);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(String str, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> lastIndexOf(value, <span class="number">0</span>, value.length,</span><br><span class="line">               str.value, <span class="number">0</span>, str.value.length, fromIndex);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(<span class="keyword">char</span>[] source, <span class="keyword">int</span> sourceOffset, <span class="keyword">int</span> sourceCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           String target, <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> lastIndexOf(source, sourceOffset, sourceCount,</span><br><span class="line">                      target.value, <span class="number">0</span>, target.value.length,</span><br><span class="line">                      fromIndex);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">lastIndexOf</span><span class="params">(<span class="keyword">char</span>[] source, <span class="keyword">int</span> sourceOffset, <span class="keyword">int</span> sourceCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           <span class="keyword">char</span>[] target, <span class="keyword">int</span> targetOffset, <span class="keyword">int</span> targetCount,</span></span></span><br><span class="line"><span class="function"><span class="params">           <span class="keyword">int</span> fromIndex)</span> </span>&#123;</span><br><span class="line">       <span class="comment">/*</span></span><br><span class="line"><span class="comment">        * Check arguments; return immediately where possible. For</span></span><br><span class="line"><span class="comment">        * consistency, don&#x27;t check for null str.</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">       <span class="keyword">int</span> rightIndex = sourceCount - targetCount;</span><br><span class="line">       <span class="keyword">if</span> (fromIndex &lt; <span class="number">0</span>) &#123;</span><br><span class="line">           <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">if</span> (fromIndex &gt; rightIndex) &#123;</span><br><span class="line">           fromIndex = rightIndex;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">/* Empty string always matches. */</span></span><br><span class="line">       <span class="keyword">if</span> (targetCount == <span class="number">0</span>) &#123;</span><br><span class="line">           <span class="keyword">return</span> fromIndex;</span><br><span class="line">       &#125;</span><br><span class="line">    </span><br><span class="line">       <span class="keyword">int</span> strLastIndex = targetOffset + targetCount - <span class="number">1</span>;</span><br><span class="line">       <span class="keyword">char</span> strLastChar = target[strLastIndex];</span><br><span class="line">       <span class="keyword">int</span> min = sourceOffset + targetCount - <span class="number">1</span>;</span><br><span class="line">       <span class="keyword">int</span> i = min + fromIndex;</span><br><span class="line">    </span><br><span class="line">   startSearchForLastChar:</span><br><span class="line">       <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">           <span class="keyword">while</span> (i &gt;= min &amp;&amp; source[i] != strLastChar) &#123;</span><br><span class="line">               i--;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">if</span> (i &lt; min) &#123;</span><br><span class="line">               <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">int</span> j = i - <span class="number">1</span>;</span><br><span class="line">           <span class="keyword">int</span> start = j - (targetCount - <span class="number">1</span>);</span><br><span class="line">           <span class="keyword">int</span> k = strLastIndex - <span class="number">1</span>;</span><br><span class="line">    </span><br><span class="line">           <span class="keyword">while</span> (j &gt; start) &#123;</span><br><span class="line">               <span class="keyword">if</span> (source[j--] != target[k--]) &#123;</span><br><span class="line">                   i--;</span><br><span class="line">                   <span class="keyword">continue</span> startSearchForLastChar;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">return</span> start - sourceOffset + <span class="number">1</span>;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<p>  <strong>从上可以看出：</strong></p>
<ul>
<li>只对外提供了int整形，String字符串两种参数的重载方法(虽然是Int型，其实我们就当做是传char也无所谓，因为虚拟机会帮我们解决这个事情的)</li>
</ul>
</li>
<li><p>substring()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">*  截取当前字符串对象的片段，组成一个新的字符串对象</span></span><br><span class="line"><span class="comment">*  beginIndex为截取的初始位置，默认截到len - 1位置</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">substring</span><span class="params">(<span class="keyword">int</span> beginIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (beginIndex &lt; <span class="number">0</span>) &#123;   <span class="comment">//小于0抛异常</span></span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(beginIndex);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">int</span> subLen = value.length - beginIndex;  <span class="comment">//新字符串的长度</span></span><br><span class="line">       <span class="keyword">if</span> (subLen &lt; <span class="number">0</span>) &#123;       <span class="comment">//小于0抛异常</span></span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(subLen);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//如果beginIndex是0，则不用截取，返回自己(非新对象)，否则截取0到subLen位置，不包括(subLen)</span></span><br><span class="line">       <span class="keyword">return</span> (beginIndex == <span class="number">0</span>) ? <span class="keyword">this</span> : <span class="keyword">new</span> String(value, beginIndex, subLen);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 截取一个区间范围</span></span><br><span class="line"><span class="comment">* [beginIndex,endIndex)，不包括endIndex</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">substring</span><span class="params">(<span class="keyword">int</span> beginIndex, <span class="keyword">int</span> endIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (beginIndex &lt; <span class="number">0</span>) &#123;</span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(beginIndex);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">if</span> (endIndex &gt; value.length) &#123;</span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(endIndex);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">int</span> subLen = endIndex - beginIndex;</span><br><span class="line">       <span class="keyword">if</span> (subLen &lt; <span class="number">0</span>) &#123;</span><br><span class="line">           <span class="keyword">throw</span> <span class="keyword">new</span> StringIndexOutOfBoundsException(subLen);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> ((beginIndex == <span class="number">0</span>) &amp;&amp; (endIndex == value.length)) ? <span class="keyword">this</span></span><br><span class="line">               : <span class="keyword">new</span> String(value, beginIndex, subLen);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="function"><span class="keyword">public</span> CharSequence <span class="title">subSequence</span><span class="params">(<span class="keyword">int</span> beginIndex, <span class="keyword">int</span> endIndex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">this</span>.substring(beginIndex, endIndex);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<p>  <strong>从上面可以看到：</strong></p>
<ul>
<li>substring函数是一个不完全闭包的区间，是[beginIndex,end)，不包括end位置</li>
<li><strong>subString的原理是通过String的构造函数实现的</strong></li>
</ul>
</li>
<li><p>concat()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* String的拼接函数</span></span><br><span class="line"><span class="comment">* 例如:String  str = &quot;abc&quot;; str.concat(&quot;def&quot;)    output: &quot;abcdef&quot;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">concat</span><span class="params">(String str)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> otherLen = str.length();<span class="comment">//获得参数字符串的长度</span></span><br><span class="line">    <span class="keyword">if</span> (otherLen == <span class="number">0</span>) &#123; <span class="comment">//如果长度为0，则代表不需要拼接，因为str为&quot;&quot;</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/****重点****/</span></span><br><span class="line">    <span class="keyword">int</span> len = value.length;  <span class="comment">//获得当前对象的长度 </span></span><br><span class="line">    <span class="comment">//将数组扩容，将value数组拷贝到buf数组中，长度为len + str.lenght</span></span><br><span class="line">    <span class="keyword">char</span> buf[] = Arrays.copyOf(value, len + otherLen); </span><br><span class="line">    str.getChars(buf, len); <span class="comment">//然后将str字符串从buf字符数组的len位置开始覆盖，得到一个完整的buf字符数组</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(buf, <span class="keyword">true</span>);<span class="comment">//构建新的String对象，调用私有的String构造方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>replace、replaceAll类函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//替换，将字符串中的oldChar字符全部替换成newChar</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">replace</span><span class="params">(<span class="keyword">char</span> oldChar, <span class="keyword">char</span> newChar)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (oldChar != newChar) &#123;    <span class="comment">//如果旧字符不等于新字符的情况下</span></span><br><span class="line">        <span class="keyword">int</span> len = value.length;  <span class="comment">//获得字符串长度</span></span><br><span class="line">        <span class="keyword">int</span> i = -<span class="number">1</span>;              <span class="comment">//flag</span></span><br><span class="line">        <span class="keyword">char</span>[] val = value; <span class="comment">/* avoid getfield opcode */</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (++i &lt; len) &#123;      <span class="comment">//循环len次</span></span><br><span class="line">            <span class="keyword">if</span> (val[i] == oldChar) &#123; <span class="comment">//找到第一个旧字符，打断循环</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (i &lt; len) &#123;   <span class="comment">//如果第一个旧字符的位置小于len</span></span><br><span class="line">            <span class="keyword">char</span> buf[] = <span class="keyword">new</span> <span class="keyword">char</span>[len]; 新<span class="keyword">new</span>一个字符数组，len个长度</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; i; j++) &#123;</span><br><span class="line">                    buf[j] = val[j];        把旧字符的前面的字符都复制到新字符数组上</span><br><span class="line">                &#125;</span><br><span class="line">            <span class="keyword">while</span> (i &lt; len) &#123;           <span class="comment">//从i位置开始遍历</span></span><br><span class="line">                <span class="keyword">char</span> c = val[i];</span><br><span class="line">                buf[i] = (c == oldChar) ? newChar : c; <span class="comment">//发生旧字符就替换，不想关的则直接复制</span></span><br><span class="line">                i++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> String(buf, <span class="keyword">true</span>);  <span class="comment">//通过新字符数组buf重构一个新String对象</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>;  <span class="comment">//如果old = new ，直接返回自己</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//替换第一个旧字符</span></span><br><span class="line"><span class="function">String <span class="title">replaceFirst</span><span class="params">(String regex, String replacement)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Pattern.compile(regex).matcher(<span class="keyword">this</span>).replaceFirst(replacement);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//当不是正规表达式时，与replace效果一样，都是全体换。如果字符串的正则表达式，则规矩表达式全体替换</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">replaceAll</span><span class="params">(String regex, String replacement)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Pattern.compile(regex).matcher(<span class="keyword">this</span>).replaceAll(replacement);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//可以用旧字符串去替换新字符串</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">replace</span><span class="params">(CharSequence target, CharSequence replacement)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Pattern.compile(target.toString(), Pattern.LITERAL).matcher(</span><br><span class="line">        <span class="keyword">this</span>).replaceAll(Matcher.quoteReplacement(replacement.toString()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>  从replace的算法中，我们可以发现，它不是从头开始遍历替换的，而是首先找到第一个要替换的字符，从要替换的字符开始遍历，发现一个替换一个。</p>
<p>  四种用法，字符全替换字符，表达式全体换字符，表达式只替换第一个字符，字符串替换字符串</p>
</li>
<li><p>matches()和contains()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* matches() 方法用于检测字符串是否匹配给定的正则表达式。</span></span><br><span class="line"><span class="comment">* regex -- 匹配字符串的正则表达式。</span></span><br><span class="line"><span class="comment">* 如：String Str = new String(&quot;www.snailmann.com&quot;);</span></span><br><span class="line"><span class="comment">* System.out.println(Str.matches(&quot;(.*)snailmann(.*)&quot;));   output:true</span></span><br><span class="line"><span class="comment">* System.out.println(Str.matches(&quot;www(.*)&quot;));             output:true</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">matches</span><span class="params">(String regex)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> Pattern.matches(regex, <span class="keyword">this</span>);   <span class="comment">//实际使用的是Pattern.matches()方法</span></span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment">//是否含有CharSequence这个子类元素，通常用于StrngBuffer,StringBuilder</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">contains</span><span class="params">(CharSequence s)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> indexOf(s.toString()) &gt; -<span class="number">1</span>;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>split()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> String[] split(String regex, <span class="keyword">int</span> limit) &#123;</span><br><span class="line">       <span class="comment">/* fastpath if the regex is a</span></span><br><span class="line"><span class="comment">        (1)one-char String and this character is not one of the</span></span><br><span class="line"><span class="comment">           RegEx&#x27;s meta characters &quot;.$|()[&#123;^?*+\\&quot;, or</span></span><br><span class="line"><span class="comment">        (2)two-char String and the first char is the backslash and</span></span><br><span class="line"><span class="comment">           the second is not the ascii digit or ascii letter.</span></span><br><span class="line"><span class="comment">        */</span></span><br><span class="line">       <span class="keyword">char</span> ch = <span class="number">0</span>;</span><br><span class="line">       <span class="keyword">if</span> (((regex.value.length == <span class="number">1</span> &amp;&amp;</span><br><span class="line">            <span class="string">&quot;.$|()[&#123;^?*+\\&quot;</span>.indexOf(ch = regex.charAt(<span class="number">0</span>)) == -<span class="number">1</span>) ||</span><br><span class="line">            (regex.length() == <span class="number">2</span> &amp;&amp;</span><br><span class="line">             regex.charAt(<span class="number">0</span>) == <span class="string">&#x27;\\&#x27;</span> &amp;&amp;</span><br><span class="line">             (((ch = regex.charAt(<span class="number">1</span>))-<span class="string">&#x27;0&#x27;</span>)|(<span class="string">&#x27;9&#x27;</span>-ch)) &lt; <span class="number">0</span> &amp;&amp;</span><br><span class="line">             ((ch-<span class="string">&#x27;a&#x27;</span>)|(<span class="string">&#x27;z&#x27;</span>-ch)) &lt; <span class="number">0</span> &amp;&amp;</span><br><span class="line">             ((ch-<span class="string">&#x27;A&#x27;</span>)|(<span class="string">&#x27;Z&#x27;</span>-ch)) &lt; <span class="number">0</span>)) &amp;&amp;</span><br><span class="line">           (ch &lt; Character.MIN_HIGH_SURROGATE ||</span><br><span class="line">            ch &gt; Character.MAX_LOW_SURROGATE))</span><br><span class="line">       &#123;</span><br><span class="line">           <span class="keyword">int</span> off = <span class="number">0</span>;</span><br><span class="line">           <span class="keyword">int</span> next = <span class="number">0</span>;</span><br><span class="line">           <span class="keyword">boolean</span> limited = limit &gt; <span class="number">0</span>;</span><br><span class="line">           ArrayList&lt;String&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">           <span class="keyword">while</span> ((next = indexOf(ch, off)) != -<span class="number">1</span>) &#123;</span><br><span class="line">               <span class="keyword">if</span> (!limited || list.size() &lt; limit - <span class="number">1</span>) &#123;</span><br><span class="line">                   list.add(substring(off, next));</span><br><span class="line">                   off = next + <span class="number">1</span>;</span><br><span class="line">               &#125; <span class="keyword">else</span> &#123;    <span class="comment">// last one</span></span><br><span class="line">                   <span class="comment">//assert (list.size() == limit - 1);</span></span><br><span class="line">                   list.add(substring(off, value.length));</span><br><span class="line">                   off = value.length;</span><br><span class="line">                   <span class="keyword">break</span>;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="comment">// If no match was found, return this</span></span><br><span class="line">           <span class="keyword">if</span> (off == <span class="number">0</span>)</span><br><span class="line">               <span class="keyword">return</span> <span class="keyword">new</span> String[]&#123;<span class="keyword">this</span>&#125;;</span><br><span class="line">    </span><br><span class="line">           <span class="comment">// Add remaining segment</span></span><br><span class="line">           <span class="keyword">if</span> (!limited || list.size() &lt; limit)</span><br><span class="line">               list.add(substring(off, value.length));</span><br><span class="line">    </span><br><span class="line">           <span class="comment">// Construct result</span></span><br><span class="line">           <span class="keyword">int</span> resultSize = list.size();</span><br><span class="line">           <span class="keyword">if</span> (limit == <span class="number">0</span>) &#123;</span><br><span class="line">               <span class="keyword">while</span> (resultSize &gt; <span class="number">0</span> &amp;&amp; list.get(resultSize - <span class="number">1</span>).length() == <span class="number">0</span>) &#123;</span><br><span class="line">                   resultSize--;</span><br><span class="line">               &#125;</span><br><span class="line">           &#125;</span><br><span class="line">           String[] result = <span class="keyword">new</span> String[resultSize];</span><br><span class="line">           <span class="keyword">return</span> list.subList(<span class="number">0</span>, resultSize).toArray(result);</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">return</span> Pattern.compile(regex).split(<span class="keyword">this</span>, limit);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">   <span class="keyword">public</span> String[] split(String regex) &#123;</span><br><span class="line">       <span class="keyword">return</span> split(regex, <span class="number">0</span>);</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br></pre></td></tr></table></figure></li>
<li><p>join()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* join方法是JDK1.8加入的新函数，静态方法</span></span><br><span class="line"><span class="comment">* 这个方法就是跟split有些对立的函数,不过join是静态方法</span></span><br><span class="line"><span class="comment">* delimiter就是分割符，后面就是要追加的可变参数，比如str1,str2,str3</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">* 例子：String.join(&quot;,&quot;,new String(&quot;a&quot;),new String(&quot;b&quot;),new String(&quot;c&quot;))</span></span><br><span class="line"><span class="comment">* output: &quot;a,b,c&quot;</span></span><br><span class="line"><span class="comment">*/</span>	</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">join</span><span class="params">(CharSequence delimiter, CharSequence... elements)</span> </span>&#123;</span><br><span class="line">      Objects.requireNonNull(delimiter);  <span class="comment">//就是检测是否为Null,是null,抛异常</span></span><br><span class="line">      Objects.requireNonNull(elements);   <span class="comment">//不是就返回自己，即nothing happen</span></span><br><span class="line">      <span class="comment">// Number of elements not likely worth Arrays.stream overhead.</span></span><br><span class="line">      StringJoiner joiner = <span class="keyword">new</span> StringJoiner(delimiter);  <span class="comment">//嗯，有兴趣自己看StringJoiner类源码啦</span></span><br><span class="line">      <span class="keyword">for</span> (CharSequence cs: elements) &#123;</span><br><span class="line">          joiner.add(cs);   <span class="comment">//既用分割符delimiter将所有可变参数的字符串分割，合并成一个字符串</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> joiner.toString();</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 功能是一样的，不过传入的参数不同</span></span><br><span class="line"><span class="comment"> * 这里第二个参数一般就是装着CharSequence子类的集合</span></span><br><span class="line"><span class="comment"> * 比如String.join(&quot;,&quot;,lists)   </span></span><br><span class="line"><span class="comment"> * list可以是一个Collection接口实现类，所含元素的基类必须是CharSequence类型</span></span><br><span class="line"><span class="comment"> * 比如String,StringBuilder,StringBuffer等</span></span><br><span class="line"><span class="comment"> */</span> </span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">join</span><span class="params">(CharSequence delimiter,</span></span></span><br><span class="line"><span class="function"><span class="params">          Iterable&lt;? extends CharSequence&gt; elements)</span> </span>&#123;</span><br><span class="line">      Objects.requireNonNull(delimiter);</span><br><span class="line">      Objects.requireNonNull(elements);</span><br><span class="line">      StringJoiner joiner = <span class="keyword">new</span> StringJoiner(delimiter);</span><br><span class="line">      <span class="keyword">for</span> (CharSequence cs: elements) &#123;</span><br><span class="line">          joiner.add(cs);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> joiner.toString();</span><br><span class="line">  &#125;</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<ul>
<li>Java 1.8加入的新功能，有点跟split对立的意思，是个静态方法</li>
<li>有两个重载方法，一个是直接传字符串数组，另个是传集合。传集合的方式是一个好功能，很方遍将集合的字符串元素拼接成一个字符串。(分割符为 <code>&quot;&quot;</code> ,well, It’s great!!)</li>
</ul>
</li>
<li><p>trim()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 去除字符串首尾部分的空值，如,&#x27; &#x27; or &quot; &quot;,非&quot;&quot;</span></span><br><span class="line"><span class="comment">* 原理是通过substring去实现的，首尾各一个指针</span></span><br><span class="line"><span class="comment">* 头指针发现空值就++，尾指针发现空值就--</span></span><br><span class="line"><span class="comment">* &#x27; &#x27;的Int值为32，其实不仅仅是去空的作用，应该是整数值小于等于32的去除掉</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">  <span class="function"><span class="keyword">public</span> String <span class="title">trim</span><span class="params">()</span> </span>&#123;</span><br><span class="line">       <span class="keyword">int</span> len = value.length; <span class="comment">//代表尾指针，实际是尾指针+1的大小</span></span><br><span class="line">	<span class="keyword">int</span> st = <span class="number">0</span>;             <span class="comment">//代表头指针</span></span><br><span class="line">       <span class="keyword">char</span>[] val = value;    <span class="comment">/* avoid getfield opcode */</span></span><br><span class="line">	</span><br><span class="line">	<span class="comment">//st&lt;len,且字符的整数值小于32则代表有空值，st++</span></span><br><span class="line">       <span class="keyword">while</span> ((st &lt; len) &amp;&amp; (val[st] &lt;= <span class="string">&#x27; &#x27;</span>)) &#123;   </span><br><span class="line">           st++;</span><br><span class="line">       &#125;</span><br><span class="line">    <span class="comment">//len - 1才是真正的尾指针，如果尾部元素的整数值&lt;=32,则代表有空值，len--</span></span><br><span class="line">       <span class="keyword">while</span> ((st &lt; len) &amp;&amp; (val[len - <span class="number">1</span>] &lt;= <span class="string">&#x27; &#x27;</span>)) &#123;</span><br><span class="line">           len--;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">//截取st到len的字符串(不包括len位置)</span></span><br><span class="line">       <span class="keyword">return</span> ((st &gt; <span class="number">0</span>) || (len &lt; value.length)) ? substring(st, len) : <span class="keyword">this</span>;</span><br><span class="line">   &#125;</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<p>  常见去首尾的空值，实际是去除首尾凡是小于32的字符</p>
</li>
<li><p>toString()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>toCharArray()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 就是将String转换为字符数组并返回</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">char</span>[] toCharArray() &#123;</span><br><span class="line">    <span class="comment">// Cannot use Arrays.copyOf because of class initialization order issues</span></span><br><span class="line">    <span class="keyword">char</span> result[] = <span class="keyword">new</span> <span class="keyword">char</span>[value.length];    <span class="comment">//定义一个要返回的空数组，长度为字符串长度</span></span><br><span class="line">    System.arraycopy(value, <span class="number">0</span>, result, <span class="number">0</span>, value.length); <span class="comment">//拷贝</span></span><br><span class="line">    <span class="keyword">return</span> result; <span class="comment">//返回</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>toLowerCase()、toUpperCase()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toLowerCase</span><span class="params">(Locale locale)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (locale == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> firstUpper;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> len = value.length;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Now check if there are any characters that need to be changed. */</span></span><br><span class="line">    scan: &#123;</span><br><span class="line">        <span class="keyword">for</span> (firstUpper = <span class="number">0</span> ; firstUpper &lt; len; ) &#123;</span><br><span class="line">            <span class="keyword">char</span> c = value[firstUpper];</span><br><span class="line">            <span class="keyword">if</span> ((c &gt;= Character.MIN_HIGH_SURROGATE)</span><br><span class="line">                &amp;&amp; (c &lt;= Character.MAX_HIGH_SURROGATE)) &#123;</span><br><span class="line">                <span class="keyword">int</span> supplChar = codePointAt(firstUpper);</span><br><span class="line">                <span class="keyword">if</span> (supplChar != Character.toLowerCase(supplChar)) &#123;</span><br><span class="line">                    <span class="keyword">break</span> scan;</span><br><span class="line">                &#125;</span><br><span class="line">                firstUpper += Character.charCount(supplChar);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (c != Character.toLowerCase(c)) &#123;</span><br><span class="line">                    <span class="keyword">break</span> scan;</span><br><span class="line">                &#125;</span><br><span class="line">                firstUpper++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">char</span>[] result = <span class="keyword">new</span> <span class="keyword">char</span>[len];</span><br><span class="line">    <span class="keyword">int</span> resultOffset = <span class="number">0</span>;  <span class="comment">/* result may grow, so i+resultOffset</span></span><br><span class="line"><span class="comment">                                * is the write location in result */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Just copy the first few lowerCase characters. */</span></span><br><span class="line">    System.arraycopy(value, <span class="number">0</span>, result, <span class="number">0</span>, firstUpper);</span><br><span class="line"></span><br><span class="line">    String lang = locale.getLanguage();</span><br><span class="line">    <span class="keyword">boolean</span> localeDependent =</span><br><span class="line">        (lang == <span class="string">&quot;tr&quot;</span> || lang == <span class="string">&quot;az&quot;</span> || lang == <span class="string">&quot;lt&quot;</span>);</span><br><span class="line">    <span class="keyword">char</span>[] lowerCharArray;</span><br><span class="line">    <span class="keyword">int</span> lowerChar;</span><br><span class="line">    <span class="keyword">int</span> srcChar;</span><br><span class="line">    <span class="keyword">int</span> srcCount;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = firstUpper; i &lt; len; i += srcCount) &#123;</span><br><span class="line">        srcChar = (<span class="keyword">int</span>)value[i];</span><br><span class="line">        <span class="keyword">if</span> ((<span class="keyword">char</span>)srcChar &gt;= Character.MIN_HIGH_SURROGATE</span><br><span class="line">            &amp;&amp; (<span class="keyword">char</span>)srcChar &lt;= Character.MAX_HIGH_SURROGATE) &#123;</span><br><span class="line">            srcChar = codePointAt(i);</span><br><span class="line">            srcCount = Character.charCount(srcChar);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            srcCount = <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (localeDependent ||</span><br><span class="line">            srcChar == <span class="string">&#x27;\u03A3&#x27;</span> || <span class="comment">// GREEK CAPITAL LETTER SIGMA</span></span><br><span class="line">            srcChar == <span class="string">&#x27;\u0130&#x27;</span>) &#123; <span class="comment">// LATIN CAPITAL LETTER I WITH DOT ABOVE</span></span><br><span class="line">            lowerChar = ConditionalSpecialCasing.toLowerCaseEx(<span class="keyword">this</span>, i, locale);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            lowerChar = Character.toLowerCase(srcChar);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> ((lowerChar == Character.ERROR)</span><br><span class="line">            || (lowerChar &gt;= Character.MIN_SUPPLEMENTARY_CODE_POINT)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (lowerChar == Character.ERROR) &#123;</span><br><span class="line">                lowerCharArray =</span><br><span class="line">                    ConditionalSpecialCasing.toLowerCaseCharArray(<span class="keyword">this</span>, i, locale);</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (srcCount == <span class="number">2</span>) &#123;</span><br><span class="line">                resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                lowerCharArray = Character.toChars(lowerChar);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">/* Grow result if needed */</span></span><br><span class="line">            <span class="keyword">int</span> mapLen = lowerCharArray.length;</span><br><span class="line">            <span class="keyword">if</span> (mapLen &gt; srcCount) &#123;</span><br><span class="line">                <span class="keyword">char</span>[] result2 = <span class="keyword">new</span> <span class="keyword">char</span>[result.length + mapLen - srcCount];</span><br><span class="line">                System.arraycopy(result, <span class="number">0</span>, result2, <span class="number">0</span>, i + resultOffset);</span><br><span class="line">                result = result2;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> x = <span class="number">0</span>; x &lt; mapLen; ++x) &#123;</span><br><span class="line">                result[i + resultOffset + x] = lowerCharArray[x];</span><br><span class="line">            &#125;</span><br><span class="line">            resultOffset += (mapLen - srcCount);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            result[i + resultOffset] = (<span class="keyword">char</span>)lowerChar;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(result, <span class="number">0</span>, len + resultOffset);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toLowerCase</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> toLowerCase(Locale.getDefault());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toUpperCase</span><span class="params">(Locale locale)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (locale == <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">int</span> firstLower;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> len = value.length;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Now check if there are any characters that need to be changed. */</span></span><br><span class="line">    scan: &#123;</span><br><span class="line">        <span class="keyword">for</span> (firstLower = <span class="number">0</span> ; firstLower &lt; len; ) &#123;</span><br><span class="line">            <span class="keyword">int</span> c = (<span class="keyword">int</span>)value[firstLower];</span><br><span class="line">            <span class="keyword">int</span> srcCount;</span><br><span class="line">            <span class="keyword">if</span> ((c &gt;= Character.MIN_HIGH_SURROGATE)</span><br><span class="line">                &amp;&amp; (c &lt;= Character.MAX_HIGH_SURROGATE)) &#123;</span><br><span class="line">                c = codePointAt(firstLower);</span><br><span class="line">                srcCount = Character.charCount(c);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                srcCount = <span class="number">1</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">int</span> upperCaseChar = Character.toUpperCaseEx(c);</span><br><span class="line">            <span class="keyword">if</span> ((upperCaseChar == Character.ERROR)</span><br><span class="line">                || (c != upperCaseChar)) &#123;</span><br><span class="line">                <span class="keyword">break</span> scan;</span><br><span class="line">            &#125;</span><br><span class="line">            firstLower += srcCount;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* result may grow, so i+resultOffset is the write location in result */</span></span><br><span class="line">    <span class="keyword">int</span> resultOffset = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">char</span>[] result = <span class="keyword">new</span> <span class="keyword">char</span>[len]; <span class="comment">/* may grow */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/* Just copy the first few upperCase characters. */</span></span><br><span class="line">    System.arraycopy(value, <span class="number">0</span>, result, <span class="number">0</span>, firstLower);</span><br><span class="line"></span><br><span class="line">    String lang = locale.getLanguage();</span><br><span class="line">    <span class="keyword">boolean</span> localeDependent =</span><br><span class="line">        (lang == <span class="string">&quot;tr&quot;</span> || lang == <span class="string">&quot;az&quot;</span> || lang == <span class="string">&quot;lt&quot;</span>);</span><br><span class="line">    <span class="keyword">char</span>[] upperCharArray;</span><br><span class="line">    <span class="keyword">int</span> upperChar;</span><br><span class="line">    <span class="keyword">int</span> srcChar;</span><br><span class="line">    <span class="keyword">int</span> srcCount;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = firstLower; i &lt; len; i += srcCount) &#123;</span><br><span class="line">        srcChar = (<span class="keyword">int</span>)value[i];</span><br><span class="line">        <span class="keyword">if</span> ((<span class="keyword">char</span>)srcChar &gt;= Character.MIN_HIGH_SURROGATE &amp;&amp;</span><br><span class="line">            (<span class="keyword">char</span>)srcChar &lt;= Character.MAX_HIGH_SURROGATE) &#123;</span><br><span class="line">            srcChar = codePointAt(i);</span><br><span class="line">            srcCount = Character.charCount(srcChar);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            srcCount = <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (localeDependent) &#123;</span><br><span class="line">            upperChar = ConditionalSpecialCasing.toUpperCaseEx(<span class="keyword">this</span>, i, locale);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            upperChar = Character.toUpperCaseEx(srcChar);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> ((upperChar == Character.ERROR)</span><br><span class="line">            || (upperChar &gt;= Character.MIN_SUPPLEMENTARY_CODE_POINT)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (upperChar == Character.ERROR) &#123;</span><br><span class="line">                <span class="keyword">if</span> (localeDependent) &#123;</span><br><span class="line">                    upperCharArray =</span><br><span class="line">                        ConditionalSpecialCasing.toUpperCaseCharArray(<span class="keyword">this</span>, i, locale);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    upperCharArray = Character.toUpperCaseCharArray(srcChar);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (srcCount == <span class="number">2</span>) &#123;</span><br><span class="line">                resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                upperCharArray = Character.toChars(upperChar);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">/* Grow result if needed */</span></span><br><span class="line">            <span class="keyword">int</span> mapLen = upperCharArray.length;</span><br><span class="line">            <span class="keyword">if</span> (mapLen &gt; srcCount) &#123;</span><br><span class="line">                <span class="keyword">char</span>[] result2 = <span class="keyword">new</span> <span class="keyword">char</span>[result.length + mapLen - srcCount];</span><br><span class="line">                System.arraycopy(result, <span class="number">0</span>, result2, <span class="number">0</span>, i + resultOffset);</span><br><span class="line">                result = result2;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> x = <span class="number">0</span>; x &lt; mapLen; ++x) &#123;</span><br><span class="line">                result[i + resultOffset + x] = upperCharArray[x];</span><br><span class="line">            &#125;</span><br><span class="line">            resultOffset += (mapLen - srcCount);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            result[i + resultOffset] = (<span class="keyword">char</span>)upperChar;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(result, <span class="number">0</span>, len + resultOffset);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">toUpperCase</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> toUpperCase(Locale.getDefault());</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>format()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//JAVA字符串格式化</span></span><br><span class="line"><span class="comment">//新字符串使用本地语言环境，制定字符串格式和参数生成格式化的新字符串。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">format</span><span class="params">(String format, Object... args)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Formatter().format(format, args).toString();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用指定的语言环境，制定字符串格式和参数生成格式化的字符串。</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">format</span><span class="params">(Locale l, String format, Object... args)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Formatter(l).format(format, args).toString();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>valueOf类函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//将Object转换为String</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(Object obj)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (obj == <span class="keyword">null</span>) ? <span class="string">&quot;null&quot;</span> : obj.toString();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将char数组转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">char</span> data[])</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(data);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将字符数组的子数组转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">char</span> data[], <span class="keyword">int</span> offset, <span class="keyword">int</span> count)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(data, offset, count);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">copyValueOf</span><span class="params">(<span class="keyword">char</span> data[], <span class="keyword">int</span> offset, <span class="keyword">int</span> count)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(data, offset, count);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">copyValueOf</span><span class="params">(<span class="keyword">char</span> data[])</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(data);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将布尔值转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">boolean</span> b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> b ? <span class="string">&quot;true&quot;</span> : <span class="string">&quot;false&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将单个字符转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">char</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">char</span> data[] = &#123;c&#125;;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> String(data, <span class="keyword">true</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将int转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Integer.toString(i);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将long转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">long</span> l)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Long.toString(l);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将float转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">float</span> f)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Float.toString(f);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将double转换为String</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">valueOf</span><span class="params">(<span class="keyword">double</span> d)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> Double.toString(d);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>  <strong>从上看：</strong></p>
</li>
<li><p>copyValueOf和valueOf在Java8看来已经是完全没有区别的函数</p>
<ul>
<li>所有的value的本质都是新new一个String对象</li>
</ul>
</li>
<li><p>intern()函数</p>
  <figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">native</span> String <span class="title">intern</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>
<p>  <strong>String类中唯一的一条本地方法，既不是用Java语言实现的方法。</strong></p>
<p>  比如str.intern(),作用就是去字符串常量池中寻找str字符串，如果有则返回str在常量池中的引用，如果没有则在常量池中创建str对象</p>
</li>
</ul>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">方陈勇</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://fangchenyong.top/2019/09/06/Java-%E6%BA%90%E7%A0%81-JDK8-String/">https://fangchenyong.top/2019/09/06/Java-%E6%BA%90%E7%A0%81-JDK8-String/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://fangchenyong.top" target="_blank">Joey</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Java/">Java</a><a class="post-meta__tags" href="/tags/%E6%BA%90%E7%A0%81/">源码</a><a class="post-meta__tags" href="/tags/String/">String</a></div><div class="post_share"><div class="social-share" data-image="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2019/10/15/%E5%9C%B0%E5%9B%BE-%E8%85%BE%E8%AE%AF%E5%9C%B0%E5%9B%BE%E5%9D%90%E6%A0%87%E6%8B%BE%E5%8F%96%E5%99%A8/"><img class="prev-cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">腾讯地图坐标选取器</div></div></a></div><div class="next-post pull-right"><a href="/2019/09/05/%E6%A1%86%E6%9E%B6-Mybatis/"><img class="next-cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Mybatis</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span> 相关推荐</span></div><div class="relatedPosts-list"><div><a href="/2021/03/20/Java-源码-JDK8-HashMap/" title="JDK8 HashMap源码"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-03-20</div><div class="title">JDK8 HashMap源码</div></div></a></div><div><a href="/2019/08/23/Java-源码-JDK8-Object/" title="JDK8 Object源码"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2019-08-23</div><div class="title">JDK8 Object源码</div></div></a></div><div><a href="/2021/04/12/Java-深入理解Java虚拟机/" title="深入理解Java虚拟机"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-12</div><div class="title">深入理解Java虚拟机</div></div></a></div><div><a href="/2019/08/23/项目-基于Netty+WebSocket简易版微信/" title="基于Netty+WebSocket简易版微信"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2019-08-23</div><div class="title">基于Netty+WebSocket简易版微信</div></div></a></div><div><a href="/2019/07/29/项目-理财产品系统/" title="理财产品系统（慕课网）"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2019-07-29</div><div class="title">理财产品系统（慕课网）</div></div></a></div><div><a href="/2019/07/20/Java-Java基础笔记/" title="Java基础笔记"><img class="cover" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2019-07-20</div><div class="title">Java基础笔记</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-avatar is-center"><img class="avatar-img" src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/3FD9B055-6361-49B7-B8CE-5BA9144BD27F.JPG" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">方陈勇</div><div class="author-info__description">一路向前</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">43</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">51</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">53</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/fangchenyong"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/fangchenyong" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:1013659102@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">个人笔记，如有疑问请联系 QQ:1013659102。</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#JDK8-String"><span class="toc-number">1.</span> <span class="toc-text">JDK8 String</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E5%AE%9A%E4%B9%89"><span class="toc-number">1.1.</span> <span class="toc-text">1.定义</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E4%B8%BB%E8%A6%81%E5%AD%97%E6%AE%B5%E5%B1%9E%E6%80%A7"><span class="toc-number">1.2.</span> <span class="toc-text">2.主要字段属性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95"><span class="toc-number">1.3.</span> <span class="toc-text">3.构造方法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95"><span class="toc-number">1.4.</span> <span class="toc-text">4.常用方法</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2021/05/06/%E7%AE%97%E6%B3%95-%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F/" title="算法"><img src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="算法"/></a><div class="content"><a class="title" href="/2021/05/06/%E7%AE%97%E6%B3%95-%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F/" title="算法">算法</a><time datetime="2021-05-05T16:00:00.000Z" title="发表于 2021-05-06 00:00:00">2021-05-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/05/06/%E7%AE%97%E6%B3%95-%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F/" title="选择排序"><img src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="选择排序"/></a><div class="content"><a class="title" href="/2021/05/06/%E7%AE%97%E6%B3%95-%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F/" title="选择排序">选择排序</a><time datetime="2021-05-05T16:00:00.000Z" title="发表于 2021-05-06 00:00:00">2021-05-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/04/12/Java-%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E8%99%9A%E6%8B%9F%E6%9C%BA/" title="深入理解Java虚拟机"><img src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="深入理解Java虚拟机"/></a><div class="content"><a class="title" href="/2021/04/12/Java-%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E8%99%9A%E6%8B%9F%E6%9C%BA/" title="深入理解Java虚拟机">深入理解Java虚拟机</a><time datetime="2021-04-11T16:00:00.000Z" title="发表于 2021-04-12 00:00:00">2021-04-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/03/21/%E9%9D%A2%E8%AF%95-%E5%B9%B6%E5%8F%91%E3%80%81%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="面试题-并发编程"><img src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="面试题-并发编程"/></a><div class="content"><a class="title" href="/2021/03/21/%E9%9D%A2%E8%AF%95-%E5%B9%B6%E5%8F%91%E3%80%81%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="面试题-并发编程">面试题-并发编程</a><time datetime="2021-03-20T16:00:00.000Z" title="发表于 2021-03-21 00:00:00">2021-03-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/03/20/%E9%9D%A2%E8%AF%95-%E9%9B%86%E5%90%88/" title="面试题-集合框架"><img src="https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="面试题-集合框架"/></a><div class="content"><a class="title" href="/2021/03/20/%E9%9D%A2%E8%AF%95-%E9%9B%86%E5%90%88/" title="面试题-集合框架">面试题-集合框架</a><time datetime="2021-03-19T16:00:00.000Z" title="发表于 2021-03-20 00:00:00">2021-03-20</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://fangchenyong.oss-cn-hangzhou.aliyuncs.com/BEF238F4E59CF4D91A694FE9C5DBC030.JPG')"><div id="footer-wrap"><div class="copyright">&copy;2019 - 2021 By 方陈勇</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text">人生没有退路！</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><div class="js-pjax"></div><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js"></script></div></body></html>